VT-d: bind IRQs to CPUs local to the node the IOMMU is on
authorJan Beulich <jbeulich@suse.com>
Tue, 13 Dec 2011 10:38:57 +0000 (11:38 +0100)
committerJan Beulich <jbeulich@suse.com>
Tue, 13 Dec 2011 10:38:57 +0000 (11:38 +0100)
This extends create_irq() to take a node parameter, allowing the
resulting IRQ to have its destination set to a CPU on that node right
away, which is more natural than having to post-adjust this (and
get e.g. a new IRQ vector assigned despite a fresh one was just
obtained).

All other callers of create_irq() pass NUMA_NO_NODE for the time being.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Keir Fraser <keir@xen.org>
xen/arch/x86/hpet.c
xen/arch/x86/io_apic.c
xen/arch/x86/irq.c
xen/arch/x86/physdev.c
xen/drivers/passthrough/amd/iommu_init.c
xen/drivers/passthrough/vtd/iommu.c
xen/include/asm-x86/io_apic.h
xen/include/asm-x86/irq.h

index c503790cb555d1b285cb30c3a20ba8aa58c2b08a..0f6d1a1fbb58f52ebfdc2472c6a0eef7cd614c14 100644 (file)
@@ -11,6 +11,7 @@
 #include <xen/smp.h>
 #include <xen/softirq.h>
 #include <xen/irq.h>
+#include <xen/numa.h>
 #include <asm/fixmap.h>
 #include <asm/div64.h>
 #include <asm/hpet.h>
@@ -334,7 +335,7 @@ static int __init hpet_assign_irq(unsigned int idx)
 {
     int irq;
 
-    if ( (irq = create_irq()) < 0 )
+    if ( (irq = create_irq(NUMA_NO_NODE)) < 0 )
         return irq;
 
     if ( hpet_setup_msi_irq(irq, hpet_events + idx) )
index 752b3f475800d63686ce1b4866a315ce14281895..f5c03b4b3542957f080f9e53601b4a39fb14115e 100644 (file)
@@ -995,7 +995,7 @@ static void __init setup_IO_APIC_irqs(void)
                 continue;
 
             if (IO_APIC_IRQ(irq)) {
-                vector = assign_irq_vector(irq);
+                vector = assign_irq_vector(irq, NULL);
                 BUG_ON(vector < 0);
                 entry.vector = vector;
                 ioapic_register_intr(irq, IOAPIC_AUTO);
@@ -2188,7 +2188,7 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int a
     if (!platform_legacy_irq(irq))
         add_pin_to_irq(irq, ioapic, pin);
 
-    vector = assign_irq_vector(irq);
+    vector = assign_irq_vector(irq, NULL);
     if (vector < 0)
         return vector;
     entry.vector = vector;
@@ -2340,7 +2340,7 @@ int ioapic_guest_write(unsigned long physbase, unsigned int reg, u32 val)
 
     if ( desc->arch.vector <= 0 || desc->arch.vector > LAST_DYNAMIC_VECTOR ) {
         add_pin_to_irq(irq, apic, pin);
-        vector = assign_irq_vector(irq);
+        vector = assign_irq_vector(irq, NULL);
         if ( vector < 0 )
             return vector;
 
index b1c5d421f3a98afbb5266bfde465747884f6e5bc..e75c06a3b645cd71b90b23b1feb649b7f0516b3e 100644 (file)
@@ -151,7 +151,7 @@ int __init bind_irq_vector(int irq, int vector, const cpumask_t *cpu_mask)
 /*
  * Dynamic irq allocate and deallocation for MSI
  */
-int create_irq(void)
+int create_irq(int node)
 {
     int irq, ret;
     struct irq_desc *desc;
@@ -168,7 +168,17 @@ int create_irq(void)
 
     ret = init_one_irq_desc(desc);
     if (!ret)
-        ret = assign_irq_vector(irq);
+    {
+        cpumask_t *mask = NULL;
+
+        if (node != NUMA_NO_NODE && node >= 0)
+        {
+            mask = &node_to_cpumask(node);
+            if (cpumask_empty(mask))
+                mask = NULL;
+        }
+        ret = assign_irq_vector(irq, mask);
+    }
     if (ret < 0)
     {
         desc->arch.used = IRQ_UNUSED;
@@ -514,7 +524,7 @@ next:
     return err;
 }
 
-int assign_irq_vector(int irq)
+int assign_irq_vector(int irq, const cpumask_t *mask)
 {
     int ret;
     unsigned long flags;
@@ -523,7 +533,7 @@ int assign_irq_vector(int irq)
     BUG_ON(irq >= nr_irqs || irq <0);
 
     spin_lock_irqsave(&vector_lock, flags);
-    ret = __assign_irq_vector(irq, desc, TARGET_CPUS);
+    ret = __assign_irq_vector(irq, desc, mask ?: TARGET_CPUS);
     if (!ret) {
         ret = desc->arch.vector;
         cpumask_copy(desc->affinity, desc->arch.cpu_mask);
index 5a4acaef69432dfab2cb54724ff538c1f1c61ea3..c1c7e54da63c4be95e8ab847eaa40ba087ab4564 100644 (file)
@@ -132,7 +132,7 @@ int physdev_map_pirq(domid_t domid, int type, int *index, int *pirq_p,
     case MAP_PIRQ_TYPE_MSI:
         irq = *index;
         if ( irq == -1 )
-            irq = create_irq();
+            irq = create_irq(NUMA_NO_NODE);
 
         if ( irq < 0 || irq >= nr_irqs )
         {
index 404638d19475280bff81f63872028133e07cc1d2..9e9dd5f855902df42fefc51dfefe6fab3b42e59b 100644 (file)
@@ -551,7 +551,7 @@ static int __init set_iommu_interrupt_handler(struct amd_iommu *iommu)
 {
     int irq, ret;
 
-    irq = create_irq();
+    irq = create_irq(NUMA_NO_NODE);
     if ( irq <= 0 )
     {
         dprintk(XENLOG_ERR, "IOMMU: no irqs\n");
index adf06cc55918b65caaef6d3cc6e127fcb11ef7ce..6bf3615c41ff3af35bc9710217608ef0a5ad85cc 100644 (file)
@@ -1096,11 +1096,13 @@ static hw_irq_controller dma_msi_type = {
     .set_affinity = dma_msi_set_affinity,
 };
 
-static int __init iommu_set_interrupt(struct iommu *iommu)
+static int __init iommu_set_interrupt(struct acpi_drhd_unit *drhd)
 {
     int irq, ret;
+    struct acpi_rhsa_unit *rhsa = drhd_to_rhsa(drhd);
 
-    irq = create_irq();
+    irq = create_irq(rhsa ? pxm_to_node(rhsa->proximity_domain)
+                          : NUMA_NO_NODE);
     if ( irq <= 0 )
     {
         dprintk(XENLOG_ERR VTDPREFIX, "IOMMU: no irq available!\n");
@@ -1109,9 +1111,9 @@ static int __init iommu_set_interrupt(struct iommu *iommu)
 
     irq_desc[irq].handler = &dma_msi_type;
 #ifdef CONFIG_X86
-    ret = request_irq(irq, iommu_page_fault, 0, "dmar", iommu);
+    ret = request_irq(irq, iommu_page_fault, 0, "dmar", drhd->iommu);
 #else
-    ret = request_irq_vector(irq, iommu_page_fault, 0, "dmar", iommu);
+    ret = request_irq_vector(irq, iommu_page_fault, 0, "dmar", drhd->iommu);
 #endif
     if ( ret )
     {
@@ -2133,7 +2135,7 @@ int __init intel_vtd_setup(void)
         if ( !vtd_ept_page_compatible(iommu) )
             iommu_hap_pt_share = 0;
 
-        ret = iommu_set_interrupt(iommu);
+        ret = iommu_set_interrupt(drhd);
         if ( ret < 0 )
         {
             dprintk(XENLOG_ERR VTDPREFIX, "IOMMU: interrupt setup failed\n");
index d561534a98a8e843bffbd02e5dabf061140506bd..a6d16f6c257e1d7aaeb65e6f81d4b133806c3b14 100644 (file)
@@ -213,9 +213,6 @@ static inline void ioapic_suspend(void) {}
 static inline void ioapic_resume(void) {}
 #endif
 
-extern int assign_irq_vector(int irq);
-extern int free_irq_vector(int vector);
-
 unsigned highest_gsi(void);
 
 int ioapic_guest_read( unsigned long physbase, unsigned int reg, u32 *pval);
index d8c724f9a813fcd1ffbf91282835c94d09a1c9b8..31475f62f65ad90bc3533bfc14df3847c5078eba 100644 (file)
@@ -155,8 +155,9 @@ int  init_irq_data(void);
 void clear_irq_vector(int irq);
 
 int irq_to_vector(int irq);
-int create_irq(void);
+int create_irq(int node);
 void destroy_irq(unsigned int irq);
+int assign_irq_vector(int irq, const cpumask_t *);
 
 extern void irq_complete_move(struct irq_desc *);